/*******************************************************************************
 * Copyright (c) 2014 Francesco Gabbrielli.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Francesco Gabbrielli - initial API and implementation
 ******************************************************************************/
package it.francescogabbrielli.android.solidalapp;

import java.util.ArrayList;
import java.util.List;

import it.francescogabbrielli.android.solidalapp.ChatMessage.Type;
import it.francescogabbrielli.android.solidalapp.SolidalApp.DataKey;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.android.gms.gcm.GoogleCloudMessaging;

public class GCMMessageReceiver extends BroadcastReceiver {
	
	private final static String TAG = SolidalApp.TAG + " GCM Receiver";
	
	private int notificationId = 0;
	
    @Override
    public void onReceive(Context context, Intent intent) {
    	
    	GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);

		Bundle extras = intent.getExtras();
	    String messageType = gcm.getMessageType(intent);
	    
	    if (!extras.isEmpty()) {  // has effect of unparcelling Bundle
	        /*
	         * Filter messages based on message type. Since it is likely that GCM will be
	         * extended in the future with new message types, just ignore any message types you're
	         * not interested in, or that you don't recognize.
	         */
	        if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
	            Log.d(TAG, "Send error: " + extras.toString());
	        } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
	        	Log.d(TAG, "Deleted messages on server: " + extras.toString());
	        } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
	        	
	        	IntentAction action = null;
	        	String title = "";
	        	String sender = extras.getString("sender");
	        	if (sender==null || "".equals(sender))
	        		sender = context.getString(R.string.anonymous_user);

	        	Log.d(TAG, "Received message: " + extras.toString());
	        	
	        	SolidalApp app = (SolidalApp) context.getApplicationContext();
	        	BaseActivity activity = app.getCurrentActivity();
	        	
	        	// multicast message used for dispatching requests
	        	if (extras.getString("type")==null) {
	        		
	            	// check current request against the one just sent
	        		SharedPreferences prefs = context.getSharedPreferences(SolidalApp.class.getCanonicalName(), Context.MODE_PRIVATE);
	            	Long currentRequestId = (Long) prefs.getLong(Constants.REQUEST_ID, 0);
	        		try {
	            		if(currentRequestId == Long.parseLong(extras.getString("id"))) {
	            			Log.w(TAG, "Receiving the request just sent!");
	            			return;
	            		}
	        		} catch(Exception e) {
	        			Log.e(TAG, "Error checking current request: "+currentRequestId, e);
	        		}
	        		
	        		action = IntentAction.GCM_REQUEST_RECEIVED;
	        		title = context.getString(R.string.request_notification_title, sender);	        	
	        	
	        	// single message used for response
	        	} else if ("accept".equals(extras.getString("type"))) {
	        		
	        		action = IntentAction.GCM_RESPONSE_RECEIVED;
	        		title = context.getString(R.string.response_notification_title, sender);
	        		
	        	// single message used for feedback
	        	} else if ("feedback".equals(extras.getString("type"))) {
	        		
	        		action = IntentAction.GCM_FEEDBACK_RECEIVED;
	        		title = context.getString(R.string.feedback_notification_title, extras.getString("message"));
	        		
	        	// chat message from request view
	        	} else if (extras.getString("type").contains("request")) {
	        		
	        		action = IntentAction.GCM_RESPONSE_CHAT_RECEIVED;
	        		title = extras.getString("message");
	        		
	        		// add message before it gets lost...
	        		@SuppressWarnings("unchecked")
	        		List<ChatMessage> chat = (List<ChatMessage>) app.getData(DataKey.CHAT_RESPONSE);
	        		if (chat==null) {
	        			chat = new ArrayList<ChatMessage>();
	        			app.setData(DataKey.CHAT_RESPONSE, chat);
	        		}
	        		chat.add(new ChatMessage(Long.valueOf(extras.getString("id")), title, Type.INCOMING));
	        		
	        	// chat message from response view
	        	} else if (extras.getString("type").contains("response")) {
	        		
	        		action = IntentAction.GCM_REQUEST_CHAT_RECEIVED;
	        		title = extras.getString("message");
	        		
	        		// add message before it gets lost...
	        		@SuppressWarnings("unchecked")
	        		List<ChatMessage> chat = (List<ChatMessage>) app.getData(DataKey.CHAT_REQUEST);
	        		if (chat==null) {
	        			chat = new ArrayList<ChatMessage>();
	        			app.setData(DataKey.CHAT_REQUEST, chat);
	        		}
	        		chat.add(new ChatMessage(Long.valueOf(extras.getString("id")), title, Type.INCOMING));
	        		
	        	// other
	        	} else {
	        		
	        		app.alert("Recevied message type "+extras.getString("type")+" unexpected");
	        				        	
	        	}
	        	
	        	/*
	        	 * if null context re-intent current activity
	        	 */
	        	if (activity!=null && action.getContextClass()==null) {
	        		
	        		Intent newIntent = new Intent(context, activity.getClass());
	        		newIntent.putExtras(extras);
	        		newIntent.setAction(action.toString());
	        		newIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
	        		context.startActivity(newIntent);
	        		
	        	/* 
	        	 * if in background or in a page different from the target one,
	        	 * send a notification that starts a new target activity:
	        	 */
	        	} else if (activity==null || activity.getClass()!=action.getContextClass()) {
	        		
	        		notify(context, action, extras, title);
	        		
        		/*
        		 * else, re-intent target activity
        		 */
	        	} else {
	        		
	        		action.start(context, extras, 
	        				Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
	        		
	        	}
	        }
	    }
	}
    
    private void notify(Context context, 
    			IntentAction action, Bundle extras, String titleString) {
    	
		NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
			.setSmallIcon(R.drawable.ic_launcher)
			.setContentTitle(titleString);
			
		String msg = extras.getString("message");
		if (!titleString.equals(msg) && !"OK".equals(msg) && !"KO".equals(msg))
			builder
				.setContentText(msg)
				.setTicker(titleString +":\n" + msg);
		
		++notificationId;
		
		Intent resultIntent = new Intent(context, action.getContextClass());
		resultIntent.setAction(action.toString());
		resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
		extras.putInt(Constants.NOTIFICATION, notificationId);
		resultIntent.putExtras(extras);
		
		TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
		stackBuilder.addParentStack(action.getContextClass());
		stackBuilder.addNextIntent(resultIntent);
		PendingIntent resultPendingIntent =
		        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);	        		

		builder.setContentIntent(resultPendingIntent);
		NotificationManager manager = 
		        (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
		Notification note = builder.setDefaults(Notification.DEFAULT_SOUND).build();
		manager.notify(notificationId, note);
	}

}
